package Entities 
{
	import flash.display.Graphics;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	/**
	 * ...
	 * @author Andy Wolff
	 */
	public class Note
	{
		private var instrument:InstrumentLayer;
		
		private var which:int;
		public function getWhich():int { return which; }
		private var start:Number;
		public function getStart():Number { return start; }
		private var end:Number;
		public function getEnd():Number { return end; }
		
		public function move(which:int, deltaX:int):void { this.which = which; start += deltaX; end += deltaX; }
		
		public function Note(instrument:InstrumentLayer, which:int, start:Number, end:Number=0) 
		{
			this.instrument = instrument;
			if (which > 7) which = 7; //we only have 8 notes (starting from channel 0)
			this.which = which;
			if (end < start) { var temp:Number = end; end = start; start = temp; } //swap if backwards :u
			start = Math.max(0, start); end = Math.max(0, end);
			this.start = start;
			this.end = end;
		}
		
		public function draw(g:Graphics, bounds:Rectangle):void {
			var r:Rectangle = getBounds(bounds);
			if (r == null) return;
			g.lineStyle(1,instrument.color);
			g.beginFill(instrument.color, 0.7);
			g.drawRect(r.x,r.y,r.width,r.height);
			g.endFill();
		}
		
		public function getBounds(bounds:Rectangle):Rectangle { 
			if (end<bounds.x || start>bounds.right) return null;
			var startPos:Number = Math.max(0, start - bounds.x);
			var endPos:Number = Math.min(bounds.width, end - bounds.x);
			var duration:Number = endPos - startPos;
			return new Rectangle(20 + startPos, 58 + 44 * which, duration, 44);
		}
		
		public function extend(p:Point):void {
			if (p.x < start) start = p.x;
			if (p.x > end) end = p.x;
		}
		
		/**
		 * Removes unnecessary/overlapping notes
		 * @param	note The potentially overlapping note to check
		 * @return Whether this note was deleted
		 */
		public function unify(note:Note):Boolean {
			if (note.end<start || note.start>end || note.which!=which || note.equals(this)) return false;
			if (note.start <= start && note.end >= end) { instrument.removeNote(this); return true; } //fully contained by other
			if (note.start > start && note.end < end) { note.start = start; note.end = end; instrument.removeNote(this); return true; } //other is fully contained by this
			if (note.start > start && note.end >= end) { note.start = start; instrument.removeNote(this); return true; } //extends to the end of the other note
			if (note.end < end && note.start <= start) { note.end = end; instrument.removeNote(this); return true; } //extends the start of the other note
			return false;
		}
		/**
		 * Deletes all parts of the note that are overlapping with the given note
		 * @param	note The subtractor
		 * @return Whether this note was deleted
		 */
		public function subtract(note:Note):Boolean {
			if (note.end<start || note.start>end || note.which!=which) return false;
			if (note.start <= start && note.end >= end) { instrument.removeNote(this); return true; } //fully contained
			if (note.start > start && note.end < end) { 
				//splits note in half
				var newNote:Note = new Note(instrument, which, note.end, end); 
				instrument.addNote(newNote);
				end = note.start;
				return false;
				}
			if (note.start > start && note.end >= end) { end = note.start; return false; } //clips the end
			if (note.end < end && note.start <= start) { 
				start = note.end; return false; } //clips the beginning
			return false;
		}
		
		public function equals(note:Note):Boolean {
			if (note.which == which && note.start == start && note.end == end) return true;
			else return false;
		}
	}

}